#include "UsbStream.h"
#include "log.h"
#include "UacUtil.h"
#include "UacIn.h"
#include "UacOut.h"
#include "UvcIn.h"

namespace Usbstream{


UsbStream::UsbStream(){
	lock_guard<mutex> lock(m_streamLock);
	m_uacin  = nullptr;
	m_uacout = nullptr;
	m_uvcin  = nullptr;
	m_enableablity = 0;
}



UsbStream::~UsbStream(){
	lock_guard<mutex> lock(m_streamLock);
	//调用三个对象的析构函数
	if(m_uacin != nullptr){
		delete(m_uacin);
		m_uacin = nullptr;
	}
	if(m_uacout != nullptr){
		delete(m_uacout);
		m_uacout = nullptr;
	}
	if(m_uvcin != nullptr){
		delete(m_uvcin);
		m_uvcin = nullptr;
	}
	m_enableablity = 0;
}

bool UsbStream::addStreamObject(int ability, int devicenum){
	lock_guard<mutex> lock(m_streamLock);
	//LOG_PrintWarn("addStreamObject support type ability:%d devicenum%d\n", ability, devicenum);
	//根据不同的ability给不同的成员变量赋值
	switch(ability){
		case UVCIN:
			m_uvcin =  new UvcIn(devicenum);
			break;
		case UACIN:
			m_uacin =  new UacIn(devicenum);
			break;
		case UACOUT:
			m_uacout = new UacOut(devicenum);
			break;
		default:
			LOG_PrintError("faild to addStreamObject not support type ability:%d\n", ability);
			break;
	}
	return true;
}

bool UsbStream::removeStreamObject(int ability){
	lock_guard<mutex> lock(m_streamLock);
	//LOG_PrintWarn("addStreamObject support type ability:%d\n", ability);
	switch(ability){
		case UVCIN:
			delete(m_uvcin);
			m_uvcin = nullptr;
			break;
		case UACIN:
			delete(m_uacin);
			m_uacin = nullptr;
			break;
		case UACOUT:
			delete(m_uacout);
			m_uacout = nullptr;
			break;
		default:
			LOG_PrintError("faild to addStreamObject not support type ability:%d\n", ability);
			break;
	}
	return true;
}


bool UsbStream::getSupportParams(int ability, Json::Value &params){
	lock_guard<mutex> lock(m_streamLock);
	UsbDevice *optObject;
	getOptObject(ability, &optObject);
	if(optObject == nullptr){
		LOG_PrintInfo("cannot support ability:%d\n", ability);
		return false;
	}
	return optObject -> getSupportParams(params);
}


bool UsbStream::setParams(int ability, const Json::Value params){
	lock_guard<mutex> lock(m_streamLock);
	UsbDevice *optObject;
	getOptObject(ability, &optObject);
	if(optObject == nullptr){
		LOG_PrintInfo("cannot support ability:%d\n", ability);
		return false;
	}
	
	return optObject -> setParams(params);
}

bool UsbStream::startStream(int ability, callback_t cb){
	lock_guard<mutex> lock(m_streamLock);
	UsbDevice *optObject;
	getOptObject(ability, &optObject);
	if(optObject == nullptr || ability == UACOUT){
		LOG_PrintInfo("cannot support ability:%d\n", ability);
		return false;
	}
	
	return optObject -> startStream(cb);
}

bool UsbStream::stopStream(int ability){
	lock_guard<mutex> lock(m_streamLock);
	UsbDevice *optObject;
	getOptObject(ability, &optObject);
	if(optObject == nullptr){
		LOG_PrintInfo("cannot support ability:%d\n", ability);
		return false;
	}
	
	return optObject -> stopStream();
}

bool UsbStream::writeStream(int ability, void *buffer, int length){
	lock_guard<mutex> lock(m_streamLock);
	UsbDevice *optObject;
	getOptObject(ability, &optObject);
	if(optObject == nullptr || ability == UACIN || ability == UVCIN){
		LOG_PrintInfo("cannot support ability:%d\n", ability);
		return false;
	}
	
	return optObject -> writeStream(buffer, length);
}

bool UsbStream::getOptObject(int ability, UsbDevice **optObject){
	switch(ability){
		case UVCIN:
			*optObject = m_uvcin;
			break;
		case UACIN:
			*optObject = m_uacin;
			break;
		case UACOUT:
			*optObject = m_uacout;
			break;
		default:
			*optObject = nullptr;
			break;
	}
	return true;
}

}
